package old;

import io.GPSPoint;
import io.SimpleParser;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.List;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.JFrame;

import org.openstreetmap.osm.data.IDataSet;
import org.openstreetmap.osm.data.MemoryDataSet;
import org.openstreetmap.osm.data.coordinates.Bounds;
import org.openstreetmap.osm.data.projection.Mercator;
import org.openstreetmap.osm.data.projection.Projection;
import org.openstreetmap.osm.io.FileLoader;

import actions.Settings;


public class OSMPanel extends JComponent {

	private IPaintVisitor visitor;
	private final IDataSet data;
	private final Map<String, List<GPSPoint>> gpsPoints;

	private long[] hilite = null;
	private CoordinateHelper ch;
	private Bounds mapBounds;
	
	public OSMPanel(IDataSet data, Map<String, List<GPSPoint>> gpsTracks) {
		this.data = data;
		this.gpsPoints = gpsTracks;
		//Testing
//		long id = 4803831;
//		Iterator<WayNode> ni = data.getWaysByID(id).getWayNodes().iterator();
//		while(ni.hasNext()) {
//			WayNode no = ni.next();
//			long nodeId = no.getNodeId();
//			Node node = data.getNodeByID(nodeId);
//			System.out.println(nodeId + " " + node.getLatitude() + " " + node.getLongitude());
//		}
		
		
		Rectangle r = new Rectangle(400, 400);
		setPreferredSize(new Dimension(r.width, r.height));
		
		mapBounds = findBounds(gpsTracks);
		Projection p = new Mercator();
		
		int zoomLevel = 20;
		ch = new CoordinateHelper(p, mapBounds, r, zoomLevel);
		visitor = new SimplePaintVisitor(ch);
		
		//addMouseListener(new PopUp(this, ch));
		MyMouseAdapter Panner = new MyMouseAdapter();
		addMouseListener(Panner);
		addMouseMotionListener(Panner);
		addMouseWheelListener(new MyMouseWheel());
		Settings.getInstance().getPropertyChangeSupport().addPropertyChangeListener(new RangeChangedListener());
	}
	
	public Bounds getMapBounds() {
		return mapBounds;
	}
	
	public CoordinateHelper getCoordinateHelper() {
		return ch;
	}
	
	private class MyMouseWheel extends MouseAdapter {
		
		@Override
		public void mouseWheelMoved(MouseWheelEvent e) {
			double factor = 1 + 0.1 * e.getWheelRotation();
			ch.scale(factor, e);
			repaint();
		}
	}
	
	private class MyMouseAdapter extends MouseAdapter {
		
		int dragged = -1;
		
		Point start;
		
		@Override
		public void mouseDragged(MouseEvent e) {
			if (dragged == -1) {
				this.start = e.getPoint();
				System.err.println("Setting start to " + start);
			}
			dragged++;
		}
		
		@Override
		public void mouseReleased(MouseEvent e) {
			dragged = -1;
			if (start != null) {
				double deltaX = e.getX() - start.getX();
				double deltaY = e.getY() - start.getY();
				System.err.println("Delta x" + deltaX + " " + deltaY);
				ch.move(deltaX, deltaY);
				repaint();
			}
		}
	}
	
	private class RangeChangedListener implements PropertyChangeListener {

		@Override
		public void propertyChange(PropertyChangeEvent evt) {
			if (evt.getPropertyName().equals(Settings.getInstance().RANGE_CHANGE)) {
				hilite = (long[]) evt.getNewValue();
				repaint();
			}
		}
		
	}
	
	private Bounds findBounds(Map<String, List<GPSPoint>> gpsTracks) {
		double minLat = Double.MAX_VALUE;
		double maxLat = -Double.MAX_VALUE;
		double minLong = Double.MAX_VALUE;
		double maxLong = -Double.MAX_VALUE;
		for (List<GPSPoint> gpsPoints : gpsTracks.values()) {
			for (GPSPoint gpsPoint : gpsPoints) {
				minLat = Math.min(minLat, gpsPoint.getLatti());
				maxLat = Math.max(maxLat, gpsPoint.getLatti());
				minLong = Math.min(minLong, gpsPoint.getLongi());
				maxLong = Math.max(maxLong, gpsPoint.getLongi());
			}
		}
		double spreadLa = (maxLong - minLong);
		double spreadLo = (maxLat - minLat);
		double maxSpread = 1.2 * Math.max(spreadLa, spreadLo);
		double centerLo = (minLong + maxLong) / 2;
		double centerLa = (minLat + maxLat) / 2;
		return new Bounds(centerLa - maxSpread / 2 , centerLo - maxSpread / 2, centerLa + maxSpread / 2 , centerLo + maxSpread / 2);
	}

	@Override
	public void paint(Graphics g) {
		Graphics2D g2 = (Graphics2D) g;
		visitor.setGraphics(g2);
		visitor.visitAll(data, g2);
		for (List<GPSPoint> gpsPointts : gpsPoints.values()) {
			visitor.visitGpsTracks(gpsPointts, hilite);
		}
	}
	
	
	
	public static void main(String[] args) throws Exception {
			//Konstanz
//			File file = new File("data/Konstanz.osm");
//			File fileGPS = new File("data/2011-01-15 15_42_22.gpx");
//			List<GPSPoint> points = GPXFileParser.parseFile(fileGPS);
		
			//Basel 
//			File file = new File("data/Basel.osm");
//			//File fileGPS = new File("data/RK_gpx _2011-01-13_1222PM.gpx");
//			//List<GPSPoint> points = GPXFileParser.parseFile(fileGPS);
//			List<GPSPoint> points = SimpleParser.parseFile(new File("C:/Users/oliver/Documents/My Dropbox/runs/04_10_2011 12o20o45.gps"));
//			
//			FileLoader fl = new FileLoader(file);
//			MemoryDataSet data = fl.parseOsm();
//			
//			
//			OSMPanel p = new OSMPanel(data, points);
//			JFrame f = new JFrame();
//			f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//			f.setContentPane(p); 
//			f.pack();
//		    f.setVisible(true);
	}
	
	
}
